//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using System;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Workflow.ComponentModel;

namespace Microsoft.Research.ScientificWorkflow.Activities
{
    /// <summary>
    /// The OpenDap URI Grid/Array Query activity appends the appropriate syntax to a base URI in order
    /// for an OpenDap server to perform a grid/array filter on the data before returning the result.
    /// 
    /// For instance, given the following inputs:
    ///   Base URI: http://plasmus.ocean.washington.edu:8080/opendap/POM/pom-2007-06-06.cdf.ascii
    ///   Variable Name: time
    ///   Start Index: 0
    ///   End Index: 100
    ///   Stride: 5
    /// 
    /// The Result URI would be: http://plasmus.ocean.washington.edu:8080/opendap/POM/pom-2007-06-06.cdf.ascii?time[0:5:100]
    /// 
    /// Mulitple instances of this activity can be chained together, along with other OpenDap query generation activities
    /// in order to produce a complete query.
    /// 
    /// The UriBuilder activity can optionally be used to create the initital base URI.
    /// </summary>
    [Name("OpenDap URI Grid Query Generator", "OpenDap Grid Query")]
    [Description("From a base URI and components of a grid/array query, creates a URI that will perform the query on an OPeNDAP server")]
    [WorkflowCategory("OpenDap")]
    public class OpenDapUriGridQuery : Activity
    {
        #region Property Definitions
        // Required input properties
        public static DependencyProperty BaseUriProperty =
            DependencyProperty.Register("BaseUri", typeof(Uri), typeof(OpenDapUriGridQuery),
            new PropertyMetadata(new Uri("http://www.microsoft.com"), DependencyPropertyOptions.Default));
        public static DependencyProperty VariableNameProperty =
            DependencyProperty.Register("VariableName", typeof(string), typeof(OpenDapUriGridQuery),
            new PropertyMetadata("variable", DependencyPropertyOptions.Default));
        public static DependencyProperty StartIndexProperty =
            DependencyProperty.Register("StartIndex", typeof(int), typeof(OpenDapUriGridQuery),
            new PropertyMetadata(0, DependencyPropertyOptions.Default));
        public static DependencyProperty EndIndexProperty =
            DependencyProperty.Register("EndIndex", typeof(int), typeof(OpenDapUriGridQuery),
            new PropertyMetadata(0, DependencyPropertyOptions.Default));
        // Optional input property
        public static DependencyProperty StrideProperty =
            DependencyProperty.Register("Stride", typeof(int), typeof(OpenDapUriGridQuery),
            new PropertyMetadata(1, DependencyPropertyOptions.Optional));
        // Output property
        public static DependencyProperty ResultUriProperty =
            DependencyProperty.Register("ResultUri", typeof(Uri), typeof(OpenDapUriGridQuery));

        // Required Input Properties
        [RequiredInputParam]
        [Name("Base URL")]
        [Description("The URL upon which to append the grid/array query")]
        public Uri BaseUri
        {
            get { return ((Uri)(base.GetValue(OpenDapUriGridQuery.BaseUriProperty))); }
            set { base.SetValue(OpenDapUriGridQuery.BaseUriProperty, value); }
        }
        [RequiredInputParam]
        [Name("Variable Name", "Variable")]
        [Description("The name of the variable to query on")]
        public string VariableName
        {
            get { return ((string)(base.GetValue(OpenDapUriGridQuery.VariableNameProperty))); }
            set { base.SetValue(OpenDapUriGridQuery.VariableNameProperty, value); }
        }
        [RequiredInputParam]
        [Name("Start Index", "Start")]
        [Description("The start index of the query (counting starts at 0)")]
        public int StartIndex
        {
            get { return ((int)(base.GetValue(OpenDapUriGridQuery.StartIndexProperty))); }
            set { base.SetValue(OpenDapUriGridQuery.StartIndexProperty, value); }
        }
        [RequiredInputParam]
        [Name("End Index", "End")]
        [Description("The end index of the query")]
        public int EndIndex
        {
            get { return ((int)(base.GetValue(OpenDapUriGridQuery.EndIndexProperty))); }
            set { base.SetValue(OpenDapUriGridQuery.EndIndexProperty, value); }
        }
        // Optional Input Property
        [RequiredInputParam]
        [Name("Stride")]
        [Description("Stride is an optional component of the query that allows skipping some of the final results. A stride of 1 will fetch all values in range. A stride of 2 will fetch every other value, etc.")]
        public int Stride
        {
            get { return ((int)(base.GetValue(OpenDapUriGridQuery.StrideProperty))); }
            set { base.SetValue(OpenDapUriGridQuery.StrideProperty, value); }
        }
        // Output Property
        [RequiredInputParam]
        [Name("Result URL", "Result")]
        [Description("The URL composed of the base URL with appended query")]
        public Uri ResultUri
        {
            get { return ((Uri)(base.GetValue(OpenDapUriGridQuery.ResultUriProperty))); }
            set { base.SetValue(OpenDapUriGridQuery.ResultUriProperty, value); }
        }
        #endregion

        /// <summary>
        /// Creates the Uri from its various parts
        /// </summary>
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            // Craft the output Uri, appending information to the input URI
            StringBuilder buff = new StringBuilder();
            buff.Append(BaseUri.ToString());
            
            if (!BaseUri.ToString().Contains('?'))
                buff.Append('?');
            else
                buff.Append('&');

            buff.Append(VariableName);
            buff.Append('[');
            buff.Append(StartIndex);
            buff.Append(':');
            if (Stride > 1)
            {
                buff.Append(Stride);
                buff.Append(':');
            }
            buff.Append(EndIndex);
            buff.Append(']');

            ResultUri = new Uri(buff.ToString());

            return ActivityExecutionStatus.Closed;
        }
    }
}